#include "lua.h"
#include "lauxlib.h"
#include "cm_os.h"
#include "app_log.h"
#include "lua_test_entry.h" // For new event system
#include <string.h>
#include <stdlib.h>

#define LUA_TIMER_METATABLE "lua_timer_mt"
#define MAX_TIMERS 16

typedef struct {
    osTimerId_t os_timer_id;
    int lua_callback_ref;
    lua_State *L;
    int is_active;
} timer_handle_t;

static timer_handle_t* g_timer_handles[MAX_TIMERS] = {NULL};

static int find_free_timer_slot() {
    for (int i = 0; i < MAX_TIMERS; i++) {
        if (g_timer_handles[i] == NULL) {
            return i;
        }
    }
    return -1;
}

static void timer_callback(void *arg) {
    timer_handle_t *handle = (timer_handle_t *)arg;
    if (handle && handle->is_active) {
        lua_event_t event;
        event.id = LUA_EVENT_TIMER;
        event.data.ival = handle->lua_callback_ref;
        lua_event_post(&event);
    }
}

// Lua: timer.start(callback, interval_ms, is_repeat) -> timer_id
static int l_timer_start(lua_State *L) {
    luaL_checktype(L, 1, LUA_TFUNCTION);
    int interval_ms = luaL_checkinteger(L, 2);
    int is_repeat = lua_toboolean(L, 3);

    int slot = find_free_timer_slot();
    if (slot == -1) {
        return luaL_error(L, "max number of timers reached");
    }

    timer_handle_t *handle = (timer_handle_t*)malloc(sizeof(timer_handle_t));
    if (!handle) {
        return luaL_error(L, "failed to allocate timer handle");
    }

    lua_pushvalue(L, 1);
    handle->lua_callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
    handle->L = L;
    handle->is_active = 1;

    osTimerType_t type = is_repeat ? osTimerPeriodic : osTimerOnce;
    handle->os_timer_id = osTimerNew(timer_callback, type, handle, NULL);

    if (handle->os_timer_id == NULL) {
        luaL_unref(L, LUA_REGISTRYINDEX, handle->lua_callback_ref);
        free(handle);
        return luaL_error(L, "failed to create os timer");
    }

    uint32_t ticks = (interval_ms * osKernelGetTickFreq()) / 1000;
    if (ticks == 0 && interval_ms > 0) {
        ticks = 1; // Ensure at least 1 tick for small intervals
    }

    if (osTimerStart(handle->os_timer_id, ticks) != osOK) {
        osTimerDelete(handle->os_timer_id);
        luaL_unref(L, LUA_REGISTRYINDEX, handle->lua_callback_ref);
        free(handle);
        return luaL_error(L, "failed to start os timer");
    }

    g_timer_handles[slot] = handle;
    lua_pushinteger(L, slot);
    return 1;
}

// Lua: timer.stop(timer_id)
static int l_timer_stop(lua_State *L) {
    int slot = luaL_checkinteger(L, 1);

    if (slot < 0 || slot >= MAX_TIMERS || g_timer_handles[slot] == NULL) {
        lua_pushboolean(L, 0);
        return 1;
    }

    timer_handle_t *handle = g_timer_handles[slot];
    handle->is_active = 0;

    osTimerStop(handle->os_timer_id);
    osTimerDelete(handle->os_timer_id);

    luaL_unref(L, LUA_REGISTRYINDEX, handle->lua_callback_ref);
    free(handle);
    g_timer_handles[slot] = NULL;

    lua_pushboolean(L, 1);
    return 1;
}

static const luaL_Reg timer_lib[] = {
    {"start", l_timer_start},
    {"stop", l_timer_stop},
    {NULL, NULL}
};

int luaopen_timer(lua_State *L) {
    luaL_newlib(L, timer_lib);
    return 1;
}
